#include "StdAfx.h"
#include "time.h"
#include "Vocoder.h"
#include "VocoderImpl.h"
#include "Overlapper.h"

static void NotifySample(std::vector<short>& destination, short* sample, unsigned int length)
{
	for(unsigned int i=0; i<length; i++)
	{
		destination.push_back(sample[i]);
	}
}

void VocoderListenerImpl::NotifyModulatorSample(short* sample, unsigned int length)
{
	if(isListening)
		NotifySample(modulatorSamples, sample, length);
}
void VocoderListenerImpl::NotifyCarrierSample(short* sample, unsigned int length)
{
	if(isListening)
		NotifySample(carrierSamples, sample, length);
}
void VocoderListenerImpl::NotifyVocoderSample(short* sample, unsigned int length)
{
	if(isListening)
		NotifySample(vocoderSamples, sample, length);
}


Vocoder::Vocoder(void)
{
	settingsProvider = NULL;
	vocoderListener = NULL;
	vocoder = new VocoderImpl();
	overlapper = NULL;
}

Vocoder::~Vocoder(void)
{
	delete vocoder;
}

void Vocoder::Initialize(Carrier* carrier, SettingsProvider* settingsProvider, VocoderListener* vocoderListener, Overlapper* overlapper=NULL)
{
	this->carrier = carrier;
	this->settingsProvider = settingsProvider;
	this->vocoderListener = vocoderListener;
	this->overlapper = overlapper;
	UpdateSettings();

	int windowLength = settings.windowLength;
	int bandCount = settings.bandCount;
	bool normalize = settings.normalizeVocoder;
	double volume = 1.0;
	int samplingRate = settings.samplingRate;
	vocoder->Initialize(windowLength, bandCount, volume, normalize, samplingRate);
}

void Vocoder::UpdateSettings()
{
	if(settingsProvider)
		settingsProvider->UpdateSettings(&settings);
}

Settings* Vocoder::GetSettings()
{
	return &settings;
}

static std::vector<long> processingTime;
static std::vector<long> carrierProcessingTime;

int Vocoder::Vocode(short* modulator, short* carrier, short* output, unsigned int length)
{
	long start = clock();
	UpdateSettings();						
	Sample vocoded(length);
	vocoder->Vocode(modulator, carrier, vocoded);

	if(overlapper)
	{
		overlapper->NextOverlap(&vocoded);
		length = vocoded.GetLength();
	}
	
	if(vocoderListener)
	{
		vocoderListener->NotifyModulatorSample(modulator, length);
		vocoderListener->NotifyCarrierSample(carrier, length);
		vocoderListener->NotifyVocoderSample(vocoded.GetData(), length);
	}
	long finish = clock();
	processingTime.push_back(finish-start);

	short* vocodedAr = vocoded.GetData();
	for(unsigned int i=0; i<length; i++)
	{
		output[i] = vocodedAr[i];
	}
	return length;
}

void Carrier::ApplyStopConsonants(short* modulatorSample, short* outputSample, unsigned int length, std::vector<SampleMarker>* markers)
{
	if(markers)
	{
		for(unsigned int i=0; i<markers->size(); i++)
		{
			SampleMarker marker = markers->at(i);
			if(marker.type==SampleMarker::PreStopConsonant || marker.type==SampleMarker::StopConsonant || marker.type==SampleMarker::PostStopConsonant)
			{
				for(unsigned int j=marker.index; j</*marker.endIndex*/length; j++)
				{
					outputSample[j] = modulatorSample[j];
				}
			}
		}
	}
}